package com.springmvc.context;

import com.bruce.exception.ContextException;
import com.springmvc.anotation.AutoWired;
import com.springmvc.anotation.Controller;
import com.springmvc.anotation.Service;
import com.springmvc.xml.XmlParser;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebApplicationContext {

    // classpath: springmvc.xml
    String contextConfigLocation;

    List<String> classNameList = new ArrayList<>();

    public Map<String ,Object> iocMap = new ConcurrentHashMap<String ,Object>();

    public WebApplicationContext(String contextConfigLocation) {
        this.contextConfigLocation = contextConfigLocation;
    }

    // 初始化spring容器
    public void refresh(){
        // 解析xml文件
        String basePackage = XmlParser.getbasePackage(contextConfigLocation.split(":")[1]);
        String[] basePackages = basePackage.split(",");
        if (basePackage.length()>0){
            for (String aPackage : basePackages) {
                excuteScanPackage(aPackage);
            }
        }
        System.out.println("扫描之后"+classNameList);
        // 实例化spring容器的bean
        excuteInstance();
        // ioc容器的对象
        System.out.println(iocMap);
        // 实现spring容器对象的注入
        excuteAutoWired();

    }

    // 初始化请求映射

    // spring容器对象的注入
    private void excuteAutoWired() {
        if (iocMap.isEmpty()){
            throw new ContextException("没有找到");
        }
        try {
            for (Map.Entry<String ,Object> entry:iocMap.entrySet()){
                String key = entry.getKey();
                Object bean = entry.getValue();
                Field[] declaredFields = bean.getClass().getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    if (declaredField.isAnnotationPresent(AutoWired.class)){
                        AutoWired autoWiredAnnotation = declaredField.getAnnotation(AutoWired.class);
                        String beanName = autoWiredAnnotation.value();
                        if ("".equals(beanName)){
                            Class<?> type = declaredField.getType();
                            beanName = type.getSimpleName().substring(0,1).toLowerCase()+type.getSimpleName().substring(1);
                        }
                        declaredField.setAccessible(true);
                        // 属性注入 调用反射 给属性赋值
                        declaredField.set(bean,iocMap.get(beanName));
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    // 实例化spring容器的对象
    private void excuteInstance() {
        if (classNameList.size()==0){
            throw new ContextException("没有实例化的class");
        }
        try {
            for (String s : classNameList) {
                Class<?> clazz = Class.forName(s);
                if (clazz.isAnnotationPresent(Controller.class)){
                    String beanName = clazz.getSimpleName().substring(0,1).toLowerCase()+clazz.getSimpleName().substring(1);
                    iocMap.put(beanName,clazz.newInstance());
                }else if (clazz.isAnnotationPresent(Service.class)){
                    Service serviceAnnotation = clazz.getAnnotation(Service.class);
                    String beanName = serviceAnnotation.value();
                    if ("".equals(beanName)){
                        Class<?>[] interfaces = clazz.getInterfaces();
                        for (Class<?> c1 : interfaces) {
                            String beanName1 = c1.getSimpleName().substring(0,1).toLowerCase()+c1.getSimpleName().substring(1);
                            iocMap.put(beanName1,clazz.newInstance());
                        }
                    }else {
                        iocMap.put(beanName,clazz.newInstance());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 扫描包
    public void excuteScanPackage(String pack){
        URL url = this.getClass().getClassLoader().getResource("/" + pack.replace("\\.", "/"));
        String path= url.getFile();
        File dir = new File(path);
        for (File f : dir.listFiles()) {
            if (f.isDirectory()){
                excuteScanPackage(pack+"."+f.getName());
            }else {
                String classPath = pack + "."+f.getName().replaceAll(".class","");
                classNameList.add(classPath);
            }
        }
    }
}
